import { TableStateProps, Pageable } from '../types'
import { reactive, computed, onMounted, toRefs } from 'vue'

/**
 * @description table 页面操作方法封装
 * @param {Function} api 获取表格数据 api 方法(必传)
 * @param {Object} initParam 获取数据初始化参数(非必传，默认为{})
 * @param {Boolean} isPageable 是否有分页(非必传，默认为true)
 * @param searchForm 表单对象，用于外部表单维护的队列， 一些清空事情 需要用此实例上的方法
 * @param {Function} dataCallBack 对后台返回的数据进行处理的方法(非必传)
 * @param {Function} beforeRequest 请求之前的一个回调， 用于清理一下存储状态
 * @param {Function} customHandlerParams 自定义处理参数的方法(非必传)
 * */
export const useTable = (
  api: (params: any) => Promise<any>,
  initParam: object = {},
  isPageable = true,
  searchForm: any,
  beforeRequest: () => void,
  dataCallBack?: (data: any) => any,
  customHandlerParams?: any,
) => {
  const state = reactive<TableStateProps>({
    // 表格数据
    tableData: [],
    // 分页数据
    pageable: {
      // 当前页数
      pageNo: 1,
      // 每页显示条数
      pageSize: 100,
      // 总条数
      total: 0
    },
    // 查询参数(只包括查询)
    searchParam: {},
    // 初始化默认的查询参数
    searchInitParam: {},
    // 总参数(包含分页和查询参数)
    totalParam: {},
    // laoding
    loading: false,
    // 排序参数
    sortParams: {},
    tableRef: null
  })

  /**
   * @description 分页查询参数(只包括分页和表格字段排序,其他排序方式可自行配置)
   * */
  const pageParam = computed({
    get: () => {
      return {
        pageNo: state.pageable.pageNo,
        pageSize: state.pageable.pageSize
      }
    },
    set: (newVal: any) => {
      console.log('我是分页更新之后的值', newVal)
    }
  })

  // 初始化的时候需要做的事情就是 设置表单查询默认值 && 获取表格数据(reset函数的作用刚好是这两个功能)
  onMounted(() => {
    reset()
  })

  /**
   * @description 获取表格数据
   * @return void
   * @param reset 是否重置搜索和分页
   * */
  const getTableList = async (res: boolean = false) => {
    try {
      state.loading = true
      beforeRequest()
      // 先把初始化参数和分页参数放到总参数里面
      if (res) {
        state.pageable.pageNo = 1
        searchForm.value.formRef.reset()
        // console.log('searchForm', searchForm.value.formRef)
      }
      Object.assign(state.totalParam, initParam, isPageable ? pageParam.value : {})
      console.log('state.sortParams',state.sortParams);
      
      if(Object.keys(state.sortParams).length > 0) {
        Object.assign(state.totalParam, {sort: {...state.sortParams}})
      }else{
        delete state.totalParam.sort
      }
      let searchParams = state.totalParam
      if (customHandlerParams) {
        searchParams = customHandlerParams(state.totalParam)
      }
      let data = await api(searchParams)
      state.loading = false
      // 修改后端返回的数据
      dataCallBack && (data = dataCallBack(data))
      state.tableData = isPageable ? data.list : data
      // 解构后台返回的分页数据
      const { pageNo, pageSize, total } = data
      // 分页信息有的接口并没有携带，需要做一个兼容
      const page = pageNo ? pageNo : state.pageable.pageNo
      const limit = pageSize ? pageSize : state.pageable.pageSize
      // 如果有分页更新分页信息
      isPageable && updatePageable({ pageNo: page, pageSize: limit, total })
    } catch (error) {
      state.loading = false
      console.log(error)
    }
  }

  /**
   * @description 更新查询参数
   * @return void
   * */
  const updatedTotalParam = () => {
    state.totalParam = {}
    // 处理查询参数，可以给查询参数加自定义前缀操作
    const nowSearchParam: { [key: string]: any } = {}
    // 防止手动清空输入框携带参数（这里可以自定义查询参数前缀）

    for (const key in state.searchParam) {
      // * 某些情况下参数为 false/0 也应该携带参数
      if (
        state.searchParam[key] ||
        state.searchParam[key] === false ||
        state.searchParam[key] === 0
      ) {
        nowSearchParam[key] = state.searchParam[key]
      }
    }
    Object.assign(state.totalParam, nowSearchParam, isPageable ? pageParam.value : {})
  }

  /**
   * @description 更新分页信息
   * @param {Object} resPageable 后台返回的分页数据
   * @return void
   * */
  const updatePageable = (resPageable: Pageable) => {
    Object.assign(state.pageable, resPageable)
  }

  /**
   * @description 表格数据查询
   * @return void
   * */
  const search = () => {
    state.pageable.pageNo = 1
    updatedTotalParam()
    getTableList()
  }

  /**
   * @description 表格数据重置
   * @return void
   * */
  const reset = () => {
    state.pageable.pageNo = 1
    state.searchParam = {}
    // 重置搜索表单的时，如果有默认搜索参数，则重置默认的搜索参数
    Object.keys(state.searchInitParam).forEach((key) => {
      state.searchParam[key] = state.searchInitParam[key]
    })
    // 重置排序
    state.tableRef && state.tableRef.clearSort()
    // 重置排序参数
    state.sortParams = {}
    updatedTotalParam()
    getTableList()
  }

  /**
   * @description 每页条数改变
   * @param {Number} val 当前条数
   * @return void
   * */
  const handleSizeChange = (size: number, current: number) => {
    state.pageable.pageNo = current
    state.pageable.pageSize = size
    getTableList()
  }

  /**
   * @description 当前页改变
   * @param {Number} val 当前页
   * @return void
   * */
  const handleCurrentChange = (val: number) => {
    state.pageable.pageNo = val
    getTableList()
  }

  /**
   * @description 更新查询参数 不包括初始化默认参数
   * @param params 搜索参数
   */
  const updateSearchParams = (params: any) => {
    state.searchParam = params
  }

  // 更新初始化查询参数
  const updateSearchInitParam = (params: any) => {
    state.searchInitParam = params
  }
  // 更新排序参数  后查询分页
  const updateSortParams = (params: any) => {
    state.sortParams = params
    getTableList()
  }
  // 更新ref
  const initTableRef = (ref: any) => {
    state.tableRef = ref
  }
  return {
    ...toRefs(state),
    getTableList,
    search,
    reset,
    handleSizeChange,
    handleCurrentChange,
    updateSearchParams,
    updateSearchInitParam,
    updateSortParams,
    initTableRef,
  }
}
